﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using FreeSwitch.EventSocket.Parser;

namespace FreeSwitch.EventSocket
{
	public class LogManager : ILogManager
	{
		private static readonly NullLogger _nullLogger = new NullLogger();
		private static ILogger _logger = _nullLogger;

		public static ILogger GetLogger(Type type)
		{
			/*if (type == typeof(MessageParser)
				|| type == typeof(EventChannel)) return new NullLogger();
			//*/
			return _logger;
		}

		public static void Assign(ILogger logger)
		{
			_logger = logger;
		}

		ILogger ILogManager.GetLogger(Type type)
		{
			return GetLogger(type);
		}
	}

	public interface ILogManager
	{
		ILogger GetLogger(Type type);
	}

	public interface ILogFilter
	{
		bool CanLog(Type source, string level);
	}

	public enum LogLevel
	{
		Trace,
		Debug,
		Info,
		Warning,
		Error
	}
	public class LogEntry
	{
		public string Message { get; set; }
		public LogLevel Level {get;set;}
		public DateTime CreatedAt { get; set; }
		public MethodBase Writer { get; set; }
	}

	public interface ILogger
	{

		void Trace(string message);
		void Trace(string message, Exception ex);
		void Error(string message);
		void Error(string message, Exception ex);
		void Debug(string message);
		void Debug(string message, Exception ex);
		void Warning(string message);
		void Warning(string message, Exception ex);


		/// <summary>
		/// Gets log source
		/// </summary>
		Type SourceType { get; }
	}

	public class ConsoleLogger : ILogger
	{
		public void Trace(string message)
		{
			Console.ForegroundColor = ConsoleColor.DarkGray;
			WriteEntry(LogLevel.Trace, message);
		}

		public void Trace(string message, Exception ex)
		{
			Console.ForegroundColor = ConsoleColor.DarkGray;
			WriteEntry(LogLevel.Trace, message, ex);
		}

		public void Error(string message)
		{
			Console.ForegroundColor = ConsoleColor.Red;
			WriteEntry(LogLevel.Error, message);
		}

		public void Error(string message, Exception ex)
		{
			Console.ForegroundColor = ConsoleColor.Red;
			WriteEntry(LogLevel.Error, message, ex);
		}

		public void Debug(string message)
		{
			Console.ForegroundColor = ConsoleColor.Gray;
			WriteEntry(LogLevel.Debug, message);
		}

		public void Debug(string message, Exception ex)
		{
			Console.ForegroundColor = ConsoleColor.Gray;
			WriteEntry(LogLevel.Debug, message, ex);
		}

		public void Warning(string message)
		{
			Console.ForegroundColor = ConsoleColor.Magenta;
			WriteEntry(LogLevel.Warning, message);
		}

		public void Warning(string message, Exception ex)
		{
			Console.ForegroundColor = ConsoleColor.Magenta;
			WriteEntry(LogLevel.Warning, message, ex);
		}

		public void WriteEntry(LogLevel level, string message, Exception ex)
		{
			var frame = new StackFrame(2);
			var trace = frame.GetMethod().ReflectedType.Name + "." + frame.GetMethod().Name;
			string tmp = String.Format("{0} {1} {2}", DateTime.Now.ToString("hh:MM:ss.fff"), trace.PadRight(40), message.Replace("\r\n", "\r\n\t"));
			Console.WriteLine(tmp);
			Console.WriteLine("\t" + ex.ToString().Replace("\r\n", "\r\n\t"));
			Console.ForegroundColor = ConsoleColor.Gray;
		}

		public void WriteEntry(LogLevel level, string message)
		{
			var frame = new StackFrame(2);
			var trace = frame.GetMethod().ReflectedType.Name + "." + frame.GetMethod().Name;
			string tmp = String.Format("{0} {1} {2}", DateTime.Now.ToString("hh:MM:ss.fff"), trace.PadRight(40), message.Replace("\r\n", "\r\n\t"));
			Console.WriteLine(tmp);
			Console.ForegroundColor = ConsoleColor.Gray;
		}

		/// <summary>
		/// Gets log source
		/// </summary>
		public Type SourceType
		{
			get { return GetType(); }
		}
	}

	public class NullLogger : ILogger
	{
		public void Trace(string message)
		{
		}

		public void Trace(string message, Exception ex)
		{
		}

		public void Error(string message)
		{
			
		}

		public void Error(string message, Exception ex)
		{
			
		}

		public void Debug(string message)
		{
			
		}

		public void Debug(string message, Exception ex)
		{
			
		}

		public void Warning(string message)
		{
			
		}

		public void Warning(string message, Exception ex)
		{
			
		}

		/// <summary>
		/// Gets log source
		/// </summary>
		public Type SourceType
		{
			get { return typeof (NullLogger); }
		}
	}

}
